home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-06-06 | 3.6 KB | 175 lines | [TEXT/CWIE] |
- unit MyStringIDs;
-
- interface
-
- uses
- Types;
-
- type
- StringID = longint;
-
- const
- null_string_id = -1;
-
- procedure StartupStringIDs;
-
- function CreateStringID( const s: Str255; var id: StringID ): OSStatus;
- procedure DestroyStringID( var id: StringID );
- function GetStringID( id: StringID; var s: Str255 ): boolean;
- function GetStrID( id: StringID ): Str255;
-
- implementation
-
- uses
- Memory,
- MyAssertions, MyStartup, MyMemory, MyLowLevel;
-
- type
- StringIDEntry = record
- id: StringID;
- hash: longint;
- reference_count: longint;
- data: Str255; { packed, pad to 4 byte boundary }
- end;
- StringIDEntryPtr = ^StringIDEntry;
-
- const
- string_id_entry_base_length = SizeOf(StringIDEntry) - 256;
-
- {$ifc do_debug}
- var
- startup_check: integer;
- {$endc}
-
- var
- strings: Handle;
- strings_count: longint;
- current_id: longint;
-
- function HashString( const s:Str255 ): longint;
- var
- value: longint;
- i: integer;
- begin
- value := 0;
- for i := 1 to length(s) do begin
- value := value * 53 + ord(s[i]);
- end;
- HashString := band(value, $7FFFFFFF);
- end;
-
- function EntryLength( var entry: StringIDEntry ): longint;
- begin
- EntryLength := string_id_entry_base_length + ((1+length(entry.data) + 3) div 4 * 4);
- end;
-
- function FindID( id: StringID ): StringIDEntryPtr;
- var
- sep: StringIDEntryPtr;
- i: longint;
- begin
- sep := StringIDEntryPtr(strings^);
- for i := 1 to strings_count do begin
- if sep^.id = id then begin
- FindID := sep;
- Exit(FindID);
- end;
- OffsetPtr( sep, EntryLength( sep^ ) );
- end;
- FindID := nil;
- end;
-
-
- function CreateStringID( const s: Str255; var id: StringID ): OSStatus;
- var
- i: longint;
- err: OSErr;
- hash: longint;
- sep: StringIDEntryPtr;
- entry: StringIDEntry;
- begin
- AssertDidStartup( startup_check );
- id := null_string_id;
- hash := HashString( s );
- sep := StringIDEntryPtr(strings^);
- for i := 1 to strings_count do begin
- if (sep^.hash = hash) & (sep^.data = s) then begin
- Inc(sep^.reference_count);
- id := sep^.id;
- CreateStringID := noErr;
- Exit(CreateStringID);
- end;
- OffsetPtr( sep, EntryLength( sep^ ) );
- end;
- Inc(current_id);
- Assert( (FindID( current_id ) = nil) );
- entry.id := current_id;
- entry.hash := hash;
- entry.reference_count := 1;
- entry.data := s;
- err := PtrAndHand( @entry, strings, EntryLength( entry ) );
- if err = noErr then begin
- Inc(strings_count);
- id := entry.id;
- end;
- CreateStringID := err;
- end;
-
- procedure DestroyStringID( var id: StringID );
- var
- sep: StringIDEntryPtr;
- begin
- AssertDidStartup( startup_check );
- sep := FindID( id );
- Assert( sep <> nil );
- if sep <> nil then begin
- Dec(sep^.reference_count);
- if sep^.reference_count = 0 then begin
- MMungerDelete( strings, SubPtrPtr( sep, strings^ ), EntryLength( sep^ ) );
- Dec(strings_count);
- end;
- end;
- id := null_string_id;
- end;
-
- function GetStringID( id: StringID; var s: Str255 ): boolean;
- var
- sep: StringIDEntryPtr;
- begin
- AssertDidStartup( startup_check );
- sep := FindID( id );
- GetStringID := sep <> nil;
- if sep <> nil then begin
- s := sep^.data;
- end else begin
- s := '';
- end;
- end;
-
- function GetStrID( id: StringID ): Str255;
- var
- junk_boolean: boolean;
- s: Str255;
- begin
- Assert( FindID( id ) <> nil );
- junk_boolean := GetStringID( id, s );
- GetStrID := s;
- end;
-
- function InitStringIDs( var msg: integer ): OSStatus;
- begin
- {$unused(msg)}
- DidStartup( startup_check );
- Assert( SizeOf( StringID ) = 4 );
- strings_count := 0;
- current_id := 1;
- InitStringIDs := MNewHandle( strings, 0 );
- end;
-
- procedure StartupStringIDs;
- begin
- SetStartup( InitStringIDs, nil, 0, nil );
- end;
-
- end.
-